(function($){
	$.fn.html5UploadFile = function(options){
		var defaults = {
				iBytesUploaded : 0,
				iBytesTotal : 0,
				iPreviousBytesLoaded : 0,
				iMaxFilesize : 20*1048576, // 20MB
				oTimer : 0,
				sendMethod:'POST',
				url:'',
				timeInterval:300
		};
		options = $.extend(defaults,options);
		
		var secondsToTime = function(secs) { // we will use this function to convert seconds in normal time format
		    var hr = Math.floor(secs / 3600);
		    var min = Math.floor((secs - (hr * 3600))/60);
		    var sec = Math.floor(secs - (hr * 3600) -  (min * 60));

		    if (hr < 10) {hr = "0" + hr; }
		    if (min < 10) {min = "0" + min;}
		    if (sec < 10) {sec = "0" + sec;}
		    if (hr) {hr = "00";}
		    return hr + ':' + min + ':' + sec;
		};
		var bytesToSize = function(bytes) {
		    var sizes = ['Bytes', 'KB', 'MB'];
		    if (bytes == 0) return 'n/a';
		    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
		    return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
		};
		
		

		
		var _this = $(this);
		_this.each(function(i,item){
			var _that = $(item);
			_that.on("change", function(evt){
			    $('#error').hide();
			    $('#error2').hide();
			    $('#abort').hide();
			    $('#warnsize').hide();
			    
			    var progressDIV = "<div id=\"progress_info\">"
			    +"	<table>"
			    +"		<tr><td colspan=\"2\"><div id=\"progress_wrapper\"><div id=\"progress\">0%</div></div></td><td><div id=\"upload_success\" style=\"display:none;\">done!</div></td></tr>"
			    +"		<tr><td width=\"50px;\"><div id=\"speed\">&nbsp;</div></td><td><div id=\"remaining\">&nbsp;</div></td><td width=\"100px;\" align=\"left\"><div id=\"b_transfered\">&nbsp;</div></td></tr>"
			    +"	</table>"
			    +"</div>";
			    _that.after(progressDIV);
			    // get selected file element
			    if(_that[0].files.length == 0)
			    {
			    	alert("please choose a file!");
			    	return;
			    }
			    var oFile = _that[0].files[0];

			    // little test for filesize
			    if (options.iMaxFilesize != -1 && oFile.size > options.iMaxFilesize) {
			        $('#warnsize').show();
			        return;
			    }
			    var fileSize = 0;
			    var progressBar = _that.parent().find("#progress_info");
			    // prepare HTML5 FileReader
			    var oReader = new FileReader();
			    oReader.onloadstart = function(){
			    	progressBar.find("#progress_wrapper").show();
			    };
			    oReader.onprogress = function(evt) {
				};
				
				oReader.onloadend = function() {
					if (oReader.error) {
						console.log(oReader.error);
					}
				};
			    oReader.onload = function(e){
			    	fileSize = bytesToSize(oFile.size);
			    };

			    // read selected file as DataURL
			    oReader.readAsDataURL(oFile);
			    
			    // get form data for POSTing
			    //var vFD = $('#upload_form').getFormData(); // for FF3
			    var vFD = new FormData();
			    vFD.append("upload_file", oFile);
			    
			    
			    // create XMLHttpRequest object, adding few event listeners, and POSTing our data
			    var oXHR = new XMLHttpRequest();        
			    oXHR.upload.addEventListener('progress', function(e) { // upload process in progress
				    if (e.lengthComputable) {
				        options.iBytesUploaded = e.loaded;
				        options.iBytesTotal = e.total;
				        var iPercentComplete = Math.round(e.loaded * 100 / e.total);
				        var iBytesTransfered = bytesToSize(options.iBytesUploaded);
				        
				        
				        if (iPercentComplete < 100) {
				        	progressBar.find('#progress').html(iPercentComplete.toString() + '%');
					        progressBar.find('#progress').css({width:(iPercentComplete * 4).toString() + 'px'});
					        progressBar.find('#b_transfered').html(iBytesTransfered);
					        
				        }
				    } else {
				    	progressBar.find('#progress').html('unable to compute');
				    }
				}, false);
			    oXHR.addEventListener('load', function(e) { // upload successfully finished
					
				    progressBar.find('#progress').html('100%');
				    progressBar.find('#progress').css({width:'400px'});
				    progressBar.find('#filesize').html(fileSize);
				    progressBar.find('#upload_success').show();
				    progressBar.find('#remaining').html('| 00:00:00');

				    clearInterval(options.oTimer);
				}, false);
			    oXHR.addEventListener('error', function(e) { // upload error
				    $('#error2').show();
				    clearInterval(options.oTimer);
				}, false);
			    oXHR.addEventListener('abort', function(e) { // upload abort
				    $('#abort').show();
				    clearInterval(options.oTimer);
				}, false);
			    oXHR.open(options.sendMethod, options.url);
			    oXHR.overrideMimeType("application/octet-stream");
			    oXHR.send(vFD);
			    oXHR.onreadystatechange = function() {
					if (oXHR.readyState == 4) {
						if (oXHR.status == 200) {
							console.log("upload complete");
							console.log("response: " + oXHR.responseText);
						}
					}
				};

			    // set inner timer
			    options.oTimer = setInterval(function() { // we will use this function to display upload speed
					
				    var iCB = options.iBytesUploaded;
				    var iDiff = iCB - options.iPreviousBytesLoaded;

				    // if nothing new loaded - exit
				    if (iDiff == 0)
				        return;

				    options.iPreviousBytesLoaded = iCB;
				    iDiff = iDiff * 2;
				    var iBytesRem = options.iBytesTotal - options.iPreviousBytesLoaded;
				    var secondsRemaining = iBytesRem / iDiff;

				    // update speed info
				    var iSpeed = iDiff.toString() + 'B/s';
				    if (iDiff > 1024 * 1024) {
				        iSpeed = (Math.round(iDiff * 100/(1024*1024))/100).toString() + 'MB/s';
				    } else if (iDiff > 1024) {
				        iSpeed =  (Math.round(iDiff * 100/1024)/100).toString() + 'KB/s';
				    }
				    var progressBar = _that.parent().find("#progress_info");
				    progressBar.find('#speed').html(iSpeed);
				    progressBar.find('#remaining').html('| ' + secondsToTime(secondsRemaining));        
				}, options.timeInterval);
			});
			
		});
	};
})(jQuery);